<!DOCTYPE html>
<html>
  <head>
    <title>扫雷</title>
    <style>
      #bar {
        text-align: center;
        margin-bottom: 20px;
      }

      .bar {
        height: 25px;
        width: 150px;
        line-height: 25px;
        display: inline-block;
        border: solid 1px #000;
        margin-left: 20px;
        margin-right: 20px;
      }

      #grid {
        margin: auto;
      }

      .blocks {
        width: 30px;
        height: 30px;
        line-height: 30px;
        display: block;
        text-align: center;
        border: solid 1px #000;
        user-select: none;
        cursor: pointer;
      }

      .blocks:hover {
        background: #0af;
      }
    </style>
  </head>

  <!-- ondragstart:防拖拽生成新页面 oncontextmenu:屏蔽右键菜单-->

  <body ondragstart="return false" oncontextmenu="self.event.returnValue=false">
    <div id="bar">
      <span class="bar">剩余雷数：<label id="count">0</label></span>
      <span class="bar">计时：<label id="time">0</label>s</span>
    </div>
    <table id="grid"></table>

    <script>
      var row = 10; //行数
      var col = 10; //列数
      var maxCount = 10; //最大地雷数量
      var isFirstOpen = true; //第一次打开方格
      var grid = init_grid(); //初始化
      var count = document.getElementById("count"); //剩余雷数
      var time = document.getElementById("time"); //计时

      //初始化矩阵 (row-行数 col-列数)
      function init_grid() {
        //生成矩阵html <tr>--行标签 <td>--列标签
        let gridHtml = "";
        for (let i = 0; i < row; i++) {
          gridHtml += "<tr>";
          for (let j = 0; j < col; j++) {
            gridHtml +=
              '<td><span class="blocks" onmousedown="block_click(' +
              i +
              "," +
              j +
              ',event)"></span></td>';
          }
          gridHtml += "<tr>";
        }
        //写入html
        document.getElementById("grid").innerHTML = gridHtml;

        //返回矩阵二维数组
        let blocks = document.getElementsByClassName("blocks");
        let grid = new Array();
        for (let i = 0; i < blocks.length; i++) {
          if (i % col === 0) {
            grid.push(new Array());
          }
          //初始化计雷数
          blocks[i].count = 0;
          grid[parseInt(i / col)].push(blocks[i]);
        }
        return grid;
      }

      //方格点击事件 _i：坐标i _j:坐标j e:鼠标事件
      function block_click(_i, _j, e) {
        //跳过已打开的方格
        if (grid[_i][_j].isOpen) {
          return;
        }

        //鼠标左键打开方格
        if (e.button === 0) {
          //第一次打开
          if (isFirstOpen) {
            isFirstOpen = false;
            let count = 0; //当前地雷数

            //生成地雷
            while (count < maxCount) {
              //生成随机坐标
              let ri = Math.floor(Math.random() * row);
              let rj = Math.floor(Math.random() * col);

              //坐标不等于第一次点击方格的坐标 && 非雷方格
              if (!(ri === _i && rj === _j) && !grid[ri][rj].isMine) {
                grid[ri][rj].isMine = true; //自定义属性isMine代表方格为地雷
                count++; //当前地雷数+1

                //更新九宫格内非雷方格的计雷数
                for (let i = ri - 1; i < ri + 2; i++) {
                  for (let j = rj - 1; j < rj + 2; j++) {
                    //判断坐标防越界
                    if (i > -1 && j > -1 && i < row && j < col) {
                      //计雷数+1
                      grid[i][j].count++;
                    }
                  }
                }
              }
            }
          }

          //执行打开方格函数
          block_open(_i, _j);

          //打开方格函数
          function block_open(_i, _j) {
            let block = grid[_i][_j];
            op(block);

            //设定打开方格的状态与样式
            function op(block) {
              block.isOpen = true; //isOpen为自定义属性，设置为true代表已打开
              block.style.background = "#ccc"; //将背景设置为灰色
              block.style.cursor = "default"; //将鼠标停留样式设置为默认
            }

            if (block.isMine) {
              //踩雷
              block.innerHTML = "雷"; //显示为 '雷'
              //遍历矩阵打开所有的地雷方格
              for (let i = 0; i < row; i++) {
                for (let j = 0; j < col; j++) {
                  //找到地雷
                  block = grid[i][j];
                  if (!block.isOpen && block.isMine) {
                    op(block); //设置打开状态和样式
                    block.innerHTML = "雷"; //显示为 '雷'
                  }
                }
              }
              //提示游戏结束
              alert("游戏结束");
            } else if (block.count === 0) {
              //打开计雷数为0的方格
              //遍历九宫格内的方格
              for (let i = _i - 1; i < _i + 2; i++) {
                for (let j = _j - 1; j < _j + 2; j++) {
                  //判断是否越界&&跳过已打开的方格&&非雷
                  if (
                    i > -1 &&
                    j > -1 &&
                    i < row &&
                    j < col &&
                    !grid[i][j].isOpen &&
                    !grid[i][j].ismine
                  ) {
                    //递归打开方格函数
                    block_open(i, j);
                  }
                }
              }
            } else {
              //打开计雷数不为0的方格
              block.innerHTML = block.count; //显示计雷数
            }
          }
        }
        //鼠标右键标记方格
        else if (e.button === 2) {
          let block = grid[_i][_j];
          if (block.innerHTML !== "▲") {
            block.innerHTML = "▲";
          } else {
            block.innerHTML = "";
          }
        }

        //判断游戏是否结束(所有的非雷方格已打开)
        for (let i = 0; i < row; i++) {
          for (let j = 0; j < col; j++) {
            if (!grid[i][j].isMine && !grid[i][j].isOpen) {
              return;
            }
          }
        }
        alert("游戏胜利");
      }
    </script>
  </body>
</html>
